#include <iostream>

#include "iostream"
#include "vector"
#include "unordered_map"
#include "unordered_set"
#include "algorithm"
#include "string"
#include "list"
#include "string.h"

struct Path{
    int from;
    int to_node;
    int life;
    Path(int from,int to_node,int life):
        to_node(to_node),life(life),from(from){}
};
struct Node{
    std::vector<Path> paths;
};

class OneLoop {
public:
//    std::vector<Node> nodes;
//    std::vector<char> visited;
//    int dfs(int n){
//        if(visited[n]){
//            return 0;
//        }
//        visited[n]=1;
//        int sum=0;
//        for(auto &path:nodes[n].paths){
//            if(curday<=path.life){
//                sum+= dfs(path.to_node);
//            }
//        }
//        return sum;
//    }
//    void clear_visited(){
//        for(auto&v:visited){
//            v=0;
//        }
//    }
//    int curday=1;
    std::vector<Path> paths;
    void sort_path(){
        for(int i=0;i<paths.size();i++){
            for(int j=0;j<paths.size()-i-1;j++){
                if(paths[j].life<paths[j+1].life){
                    std::swap(paths[j],paths[j+1]);
                }
            }
        }
    }
    std::vector<int> bingchaji;
    int find(int n){
        if(n==bingchaji[n-1]){
            return n;
        }else{
            bingchaji[n-1]= find(bingchaji[n-1]);
            return bingchaji[n-1];
        }
    }

    //ret if merged
    bool merge(int a,int b){
        int fa= find(a);
        int fb=find(b);
        if(fa!=fb){
            bingchaji[find(b)-1] = find(a);
            return true;
        }else{
            return false;
        }
    }
//    std::unordered_map<int,char> node_appear;
    bool run(
            int n,int m
//            std::string&s1,std::string& s2
    ) {
        bingchaji.resize(n);
//        nodes.resize(n);
//        visited.resize(n);
        int res=0;
//        int max_day=0;
        for(int i=0;i<m;i++){
            int f,t,l;
            std::cin>>f>>t>>l;
//            max_day= std::max(max_day,l);
            paths.emplace_back(f,t,l);
//            nodes[f-1].paths.push_back(Path(t-1,l));
//            nodes[t-1].paths.push_back(Path(f-1,l));
        }
        for(int i=0;i<bingchaji.size();i++){
            bingchaji[i]=i+1;
        }
        sort_path();
        int scan_i=0;
        for(;scan_i<paths.size();){
            bool has_new_node=false;
            int first_day_cnt=paths[scan_i].life;
            while(scan_i<paths.size()&&paths[scan_i].life==first_day_cnt){
                auto &path=paths[scan_i];
                if(merge(path.from,path.to_node)){
                    has_new_node= true;
                }
                scan_i++;
            }
            if(has_new_node){
                res++;
            }
        }

//        for(int i=1;i<max_day;i++){
//            clear_visited();
//            if(dfs(0)!=nodes.size()){
//                res++;
//            }
//        }
        printf("%d\n",res);
        return false;
    }
};

class Solution {
public:
    void run() {

        bool first = true;
        int a, b, c, d, e;
        //        std::cin >> a;
//        std::string s1,s2;
//        while (1){
        while (
//                std::getline(std::cin,s1)
                std::cin >> a >> b
//                1
                ) {
//            std::getline(std::cin,s2);
            OneLoop l;
            if (!l.run(a,b)) {
//                return;
            }
        }


    }
};

int main() {

    //    bool cur_num= true;
    Solution().run();
    return 0;
}

